from django.shortcuts import render
from django.utils import timezone
from django.views import View
from django import http
from django.core.paginator import Paginator, EmptyPage

from contents.utils import get_categories
from .models import GoodsCategory, SKU, GoodsVisitCount
from .utils import get_breadcrumb
from meiduo_mall.utils.response_code import RETCODE


class ListView(View):
    """商品列表界面"""
    def get(self, request, category_id, page_num):

        try:
            category_model = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('category_id不存在')

        # TODO:如果验证当前查询出来的商品类别是三级类别, 作业
        # try:
        #     category_model = category_model.parent.parent  # 此行报错,说明category_model是一级
        # except:
        #     return http.HttpResponseForbidden('类别有误')
        #
        # if category_model.parent.parent is None:  # 此行if成立说明它是二级
        #     return http.HttpResponseForbidden('类别有误')

        if category_model.subs.all().exists():  #如果是三级来取下级会返回一个空的QuerySet
            return http.HttpResponseForbidden('类别有误')


        # 获取查询参数中的排序规则
        sort = request.GET.get('sort')
        if sort == 'price':
            sort_fields = '-price'
        elif sort == 'hot':
            sort_fields = 'sales'
        else:
            sort = 'default'
            sort_fields = '-create_time'

        # 查询当前三级类别下的所有sku
        sku_qs = category_model.sku_set.filter(is_launched=True).order_by(sort_fields)
        # # 分页目的?  数据切片查询,减轻服务压力,提升界面响应速度
        # # 每页显示5个sku   # 14
        # # 总页数 = 总数量 // 5 + 1 if (总数量 % 5) else 0
        # page = 5  # 每页显示5个sku
        # total_count = sku_qs.count()
        # total_page = total_count // page + 1 if (total_count % page) else 0
        # # 指定页显示数据
        # page_num = int(page_num)
        # page_skus = sku_qs[(page_num - 1) * page: page * page_num]  # 第一页
        # paginator = Paginator(object_list='传入要分页的数据', per_page='传入每页显示多少条')
        # 创建分页器对象
        paginator = Paginator(sku_qs, 5)
        # 获取总页数
        total_page = paginator.num_pages
        # 获取指定页数据
        try:
            page_skus = paginator.page(page_num)
        except EmptyPage:
            return http.HttpResponseForbidden('不存在你所指定的这一页')

        context = {
            'categories': get_categories(),  # 商品类型数据
            'breadcrumb': get_breadcrumb(category_model),  # 面包屑数据
            'category': category_model,  # 三级类型模型对象
            'sort': sort,  # 排序字段
            'page_skus': page_skus,  # 当前页要展示的所有sku数据
            'page_num': page_num,  # 当前显示第几页
            'total_page': total_page,  # 总页数
        }
        return render(request, 'list.html', context)


class HotGoodsView(View):
    """热销排行"""
    def get(self, request, category_id):
        # 校验
        try:
            cat3 = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('category_id不存在')


        # 查询当前类别下销量最高的前两个sku
        sku_qs = cat3.sku_set.filter(is_launched=True).order_by('-sales')[:2]
        # 将sku查询集中的模型转字典并添加到列表中
        sku_list = []  # 用来包装sku字典
        for sku in sku_qs:
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'price': sku.price,
                'default_image_url': sku.default_image.url
            })
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'hot_skus': sku_list})


class DetailView(View):
    """商品详情界面"""
    def get(self, request, sku_id):
        try:
            sku = SKU.objects.get(id=sku_id, is_launched=True)
        except SKU.DoesNotExist:
            return render(request, '404.html')

        category = sku.category  # 获取当前sku所对应的三级分类

        # 查询当前sku所对应的spu
        spu = sku.spu

        """1.准备当前商品的规格选项列表 [8, 11]"""
        # 获取出当前正显示的sku商品的规格选项id列表
        current_sku_spec_qs = sku.specs.order_by('spec_id')
        current_sku_option_ids = []  # [8, 11]
        for current_sku_spec in current_sku_spec_qs:
            current_sku_option_ids.append(current_sku_spec.option_id)

        """2.构造规格选择仓库
        {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8}
        """
        # 构造规格选择仓库
        temp_sku_qs = spu.sku_set.all()  # 获取当前spu下的所有sku
        # 选项仓库大字典
        spec_sku_map = {}  # {(8, 11): 3, (8, 12): 4, (9, 11): 5, (9, 12): 6, (10, 11): 7, (10, 12): 8}
        for temp_sku in temp_sku_qs:
            # 查询每一个sku的规格数据
            temp_spec_qs = temp_sku.specs.order_by('spec_id')
            temp_sku_option_ids = []  # 用来包装每个sku的选项值
            for temp_spec in temp_spec_qs:
                temp_sku_option_ids.append(temp_spec.option_id)
            spec_sku_map[tuple(temp_sku_option_ids)] = temp_sku.id

        """3.组合 并找到sku_id 绑定"""
        spu_spec_qs = spu.specs.order_by('id')  # 获取当前spu中的所有规格

        for index, spec in enumerate(spu_spec_qs):  # 遍历当前所有的规格
            spec_option_qs = spec.options.all()  # 获取当前规格中的所有选项
            temp_option_ids = current_sku_option_ids[:]  # 复制一个新的当前显示商品的规格选项列表
            for option in spec_option_qs:  # 遍历当前规格下的所有选项
                temp_option_ids[index] = option.id  # [8, 12]
                option.sku_id = spec_sku_map.get(tuple(temp_option_ids))  # 给每个选项对象绑定下他sku_id属性

            spec.spec_options = spec_option_qs  # 把规格下的所有选项绑定到规格对象的spec_options属性上

        context = {
            'categories': get_categories(),  # 商品分类
            'breadcrumb': get_breadcrumb(category),  # 面包屑导航
            'sku': sku,  # 当前要显示的sku模型对象
            'category': category,  # 当前的显示sku所属的三级类别
            'spu': spu,  # sku所属的spu
            'spec_qs': spu_spec_qs,  # 当前商品的所有规格数据
        }
        return render(request, 'detail.html', context)


class GoodsVisitView(View):
    """商品类别访问类统计"""
    def post(self, request, category_id):

        # 校验
        try:
            category = GoodsCategory.objects.get(id=category_id)
        except GoodsCategory.DoesNotExist:
            return http.HttpResponseForbidden('category_id不存在')

        if category.subs.all().exists():
            return http.HttpResponseForbidden('类别有误')

        # 获取当天日期
        # date = timezone.localtime()  # 获取当前系统时间
        # date = timezone.localdate()  # 获取当前系统日期
        date = timezone.now()  # 获取当前系统的日期时间
        try:
            # 查询当前类别今日是否访问过
            goods_visit = GoodsVisitCount.objects.get(category_id=category_id, date=date)
        except GoodsVisitCount.DoesNotExist:
            # 如果今日此类别没有访问过就新增访问记录
            goods_visit = GoodsVisitCount(category_id=category_id)


        # 如果今日此类别访问过就累加count
        goods_visit.count += 1
        goods_visit.save()
        # 响应
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})